﻿using System;
using System.IO;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Collections.ObjectModel;
using System.ComponentModel;
using HCI.Questionaire.Controls.Command;
using System.Windows.Shapes;
using System.Windows.Controls.Primitives;

namespace HCI.Questionaire.Controls
{
    public partial class PagingControl : UserControl
    {
        public event Action<int> PageIndexChange;
        private int _PageCount;

        public PagingControl()
        {

            this.InitializeCommands();

            this.InitializeComponent();

            // Insert code required on object creation below this point.
            this.ReevaluateCommands();
        }

        #region Public Properties
        public int TotalResults
        {
            get { return (int)base.GetValue(TotalResultsProperty); }
            set
            {
                base.SetValue(TotalResultsProperty, value);
                this.GotoFirstPage(null);
            }
        }

        public int ResultsPerPage
        {
            get
            {
                int returnVal = (int)base.GetValue(ResultsPerPageProperty);
                if (returnVal <= 0)
                {
                    return 10;
                }
                else
                {
                    return returnVal;
                }
            }
            set
            {
                base.SetValue(ResultsPerPageProperty, value);
                this.GotoFirstPage(null);
            }
        }

        public int CurrentPage
        {
            get { return (int)base.GetValue(CurrentPageProperty); }
            set
            {
                base.SetValue(CurrentPageProperty, value);

                //for (int index = 0; index < this.PageNavigateCommands.Count; ++index)
                //{
                //    if (this.PageNavigateCommands[index].Index != this.CurrentPage)
                //    {
                //        this.PageNavigateCommands[index].IsSelected = false;
                //    }
                //    else
                //    {
                //        this.PageNavigateCommands[index].IsSelected = true;
                //    }
                //}

                this.ReevaluateCommands();
                this.OnPageIndexChange();
            }
        }

        public int PageCount
        {
            get { return (int)base.GetValue(PageCountProperty); }
            set
            {
                base.SetValue(PageCountProperty, value);
                this.GotoFirstPage(null);
            }
        }

        public static readonly DependencyProperty TotalResultsProperty = DependencyProperty.Register("TotalResults", typeof(int), typeof(PagingControl), new PropertyMetadata(new PropertyChangedCallback(OnTotalResultsChanged)));
        public static readonly DependencyProperty ResultsPerPageProperty = DependencyProperty.Register("ResultsPerPage", typeof(int), typeof(PagingControl), new PropertyMetadata((s, e) => { ((PagingControl)s).ResultsPerPage = (int)e.NewValue; }));
        public static readonly DependencyProperty CurrentPageProperty = DependencyProperty.Register("CurrentPage", typeof(int), typeof(PagingControl), new PropertyMetadata((s, e) => { ((PagingControl)s).CurrentPage = (int)e.NewValue; }));
        public static readonly DependencyProperty PageCountProperty = DependencyProperty.Register("PageCount", typeof(int), typeof(PagingControl), new PropertyMetadata((s, e) => { ((PagingControl)s).PageCount = (int)e.NewValue; }));

        private ObservableCollection<PageNavigateCommand> pageNavigateCommands = new ObservableCollection<PageNavigateCommand>();
        //public ObservableCollection<PageNavigateCommand> PageNavigateCommands
        //{
        //    get { return pageNavigateCommands; }
        //}
        #endregion

        private static void OnTotalResultsChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            PagingControl control = (PagingControl)sender;
            control.TotalResults = (int)e.NewValue;
        }

        private void GotoFirstPage(object arg)
        {
            this.CurrentPage = 1;
            //this.ReevaluateCommands();

            int maxPossiblePageCount = (int)Math.Ceiling((double)(this.TotalResults / this.ResultsPerPage));
            int displayedPageCount = Math.Min(maxPossiblePageCount, this.PageCount);
            //this.PageNavigateCommands.Clear();

            if (displayedPageCount > 0)
            {
                for (int i = 1; i <= displayedPageCount; ++i)
                {
                    PageNavigateCommand command = new PageNavigateCommand(new DelegateCommand.SimpleEventHandler(this.NavigateToPage));
                    command.Index = i;
                    //this.PageNavigateCommands.Add(command);
                }

                //this.PageNavigateCommands[0].IsSelected = true;
            }
        }

        private void GotoLastPage(object arg)
        {
            //this.CurrentPage = (int)Math.Ceiling((double)(this.TotalResults / this.ResultsPerPage)); ;
            ////this.ReevaluateCommands();

            //int maxPossiblePageCount = (int)Math.Ceiling((double)(this.TotalResults / this.ResultsPerPage));
            //int endIndex = maxPossiblePageCount;
            //int startIndex = ((maxPossiblePageCount - PageCount) >= 0) ? (maxPossiblePageCount - PageCount) : 1;
            ////this.PageNavigateCommands.Clear();

            //for (int i = startIndex; i < endIndex; ++i)
            //{
            //    PageNavigateCommand command = new PageNavigateCommand(new DelegateCommand.SimpleEventHandler(this.NavigateToPage));
            //    command.Index = i + 1;
            //    //this.PageNavigateCommands.Add(command);
            //}

            this.CurrentPage = this._PageCount;
            this.ReevaluateCommands();
            //this.PageNavigateCommands[this.PageNavigateCommands.Count - 1].IsSelected = true;
        }

        private void GotoNextPage(object arg)
        {
            if (this.CurrentPage < this._PageCount)
                this.CurrentPage = this.CurrentPage + 1;
            this.ReevaluateCommands();

            //if (this.CurrentPage > this.PageNavigateCommands[this.PageNavigateCommands.Count - 1].Index)
            //{
            //    this.PageNavigateCommands.RemoveAt(0);

            //    PageNavigateCommand command = new PageNavigateCommand(new DelegateCommand.SimpleEventHandler(this.NavigateToPage));
            //    command.Index = this.CurrentPage;
            //    command.IsSelected = true;
            //    this.PageNavigateCommands.Add(command);
            //}
        }

        private void GotoPreviousPage(object arg)
        {
            this.CurrentPage = this.CurrentPage - 1;
            //this.ReevaluateCommands();

            //if (this.CurrentPage < this.PageNavigateCommands[0].Index)
            //{
            //    //this.PageNavigateCommands.RemoveAt(this.PageNavigateCommands.Count - 1);

            //    PageNavigateCommand command = new PageNavigateCommand(new DelegateCommand.SimpleEventHandler(this.NavigateToPage));
            //    command.Index = this.CurrentPage;
            //    command.IsSelected = true;
            //    this.PageNavigateCommands.Insert(0, command);
            //}
        }

        private void NavigateToPage(object arg)
        {
            this.CurrentPage = (int)arg;
        }

        private void InitializeCommands()
        {
            firstPageCommand = new DelegateCommand(new DelegateCommand.SimpleEventHandler(this.GotoFirstPage));
            nextPageCommand = new DelegateCommand(new DelegateCommand.SimpleEventHandler(this.GotoNextPage));
            lastPageCommand = new DelegateCommand(new DelegateCommand.SimpleEventHandler(this.GotoLastPage));
            previousPageCommand = new DelegateCommand(new DelegateCommand.SimpleEventHandler(this.GotoPreviousPage));
        }

        private void ReevaluateCommands()
        {
            this.btnFirst.IsEnabled = true;
            this.btnPrevious.IsEnabled = true;
            this.btnNext.IsEnabled = true;
            this.btnLast.IsEnabled = true;

            if (this.CurrentPage <= 1)
            {
                this.btnFirst.IsEnabled = false;
                this.btnPrevious.IsEnabled = false;
            }

            if (this.CurrentPage >= this._PageCount)
            {
                this.btnNext.IsEnabled = false;
                this.btnLast.IsEnabled = false;
            }
        }

        #region Commands
        private DelegateCommand firstPageCommand;
        private DelegateCommand lastPageCommand;
        private DelegateCommand nextPageCommand;
        private DelegateCommand previousPageCommand;

        public DelegateCommand FirstPageCommand
        {
            get { return this.firstPageCommand; }
        }

        public DelegateCommand NextPageCommand
        {
            get { return this.nextPageCommand; }
        }

        public DelegateCommand PreviousPageCommand
        {
            get { return this.previousPageCommand; }
        }

        public DelegateCommand LastPageCommand
        {
            get { return this.lastPageCommand; }
        }
        #endregion

        public void SetPageCount(int pageCount)
        {
            var pageInfo = new System.Collections.Generic.List<PageNavigateCommand>();
            for (int i = 1; i <= pageCount; i++)
            {
                pageInfo.Add(new PageNavigateCommand(o => { }) { Index = i });
            }

            this.Pages.ItemsSource = pageInfo;

            this._PageCount = pageCount;
        }


        private void page_Click(object sender, RoutedEventArgs e)
        {
            this.NavigateToPage(int.Parse(((ToggleButton)sender).Content.ToString()));
        }

        private void OnPageIndexChange()
        {
            if (this.PageIndexChange != null)
            {
                this.PageIndexChange(this.CurrentPage -1);
            }
        }


        private void First_Click(object sender, RoutedEventArgs e)
        {
            this.GotoFirstPage(null);
        }

        private void Last_Click(object sender, RoutedEventArgs e)
        {
            this.GotoLastPage(null);
        }

        private void Next_Click(object sender, RoutedEventArgs e)
        {
            this.GotoNextPage(null);
        }

        private void Previous_Click(object sender, RoutedEventArgs e)
        {
            this.GotoPreviousPage(null);
        }
    }

    public class PageNavigateCommand : INotifyPropertyChanged
    {
        private int index;

        public int Index
        {
            get { return index; }
            set { index = value; }
        }

        private bool isSelected;

        public bool IsSelected
        {
            get { return isSelected; }
            set
            {
                isSelected = value;
                this.OnPropertyChanged("IsSelected");
            }
        }

        private DelegateCommand navigateCommand;
        public DelegateCommand NavigateCommand
        {
            get { return this.navigateCommand; }
        }

        public PageNavigateCommand(DelegateCommand.SimpleEventHandler handler)
        {
            this.navigateCommand = new DelegateCommand(handler);
        }

        
        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        private void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}